# 增强的工作流功能视图
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.contrib import messages
from django.core.paginator import Paginator
from django.db.models import Count, Avg, Q, F
from django.utils import timezone
from datetime import datetime, timedelta
import json
import logging

from .models_workflow import WorkflowTemplate, WorkflowInstance, WorkflowStepTask, WorkflowHistory
from .workflow_engine import workflow_engine
from .models import Asset, AssetCategory, Department

logger = logging.getLogger(__name__)


@login_required
@permission_required('assets.add_workflowtemplate', raise_exception=True)
def workflow_designer(request):
    """工作流可视化设计器"""
    
    # 获取现有模板（用于编辑）
    template_id = request.GET.get('template_id')
    template = None
    
    if template_id:
        try:
            template = WorkflowTemplate.objects.get(id=template_id)
        except WorkflowTemplate.DoesNotExist:
            messages.error(request, '工作流模板不存在')
            return redirect('assets:workflow_template_list')
    
    context = {
        'template': template,
        'template_types': WorkflowTemplate.TEMPLATE_TYPE_CHOICES,
    }
    
    return render(request, 'assets/workflow/designer.html', context)


@login_required
@permission_required('assets.add_workflowtemplate', raise_exception=True)
@require_http_methods(["POST"])
def save_workflow_template(request):
    """保存工作流模板"""
    
    try:
        data = json.loads(request.body)
        
        name = data.get('name')
        template_type = data.get('template_type')
        description = data.get('description', '')
        workflow_definition = data.get('workflow_definition')
        template_id = data.get('template_id')  # 用于更新现有模板
        
        if not all([name, template_type, workflow_definition]):
            return JsonResponse({
                'success': False,
                'message': '缺少必要参数'
            }, status=400)
        
        # 验证工作流定义
        validation_result = validate_workflow_definition(workflow_definition)
        if not validation_result['valid']:
            return JsonResponse({
                'success': False,
                'message': '工作流定义验证失败',
                'errors': validation_result['errors']
            }, status=400)
        
        # 保存或更新模板
        if template_id:
            # 更新现有模板
            template = get_object_or_404(WorkflowTemplate, id=template_id)
            template.name = name
            template.template_type = template_type
            template.description = description
            template.workflow_definition = workflow_definition
            template.save()
            
            message = '工作流模板更新成功'
        else:
            # 创建新模板
            template = WorkflowTemplate.objects.create(
                name=name,
                template_type=template_type,
                description=description,
                workflow_definition=workflow_definition,
                created_by=request.user
            )
            
            message = '工作流模板创建成功'
        
        return JsonResponse({
            'success': True,
            'message': message,
            'template_id': template.id
        })
        
    except Exception as e:
        logger.error(f"保存工作流模板失败: {e}")
        return JsonResponse({
            'success': False,
            'message': f'保存失败: {str(e)}'
        }, status=500)


def validate_workflow_definition(workflow_def):
    """验证工作流定义"""
    
    errors = []
    
    try:
        steps = workflow_def.get('steps', [])
        
        if not steps:
            errors.append('工作流至少需要一个步骤')
            return {'valid': False, 'errors': errors}
        
        step_ids = set()
        
        # 验证每个步骤
        for i, step in enumerate(steps):
            step_id = step.get('id')
            if not step_id:
                errors.append(f'步骤 {i+1} 缺少ID')
                continue
            
            if step_id in step_ids:
                errors.append(f'步骤ID "{step_id}" 重复')
            else:
                step_ids.add(step_id)
            
            if not step.get('name'):
                errors.append(f'步骤 "{step_id}" 缺少名称')
            
            if not step.get('type'):
                errors.append(f'步骤 "{step_id}" 缺少类型')
            
            # 验证依赖关系
            depends_on = step.get('depends_on', [])
            for dep_id in depends_on:
                if dep_id not in step_ids and dep_id not in [s.get('id') for s in steps]:
                    errors.append(f'步骤 "{step_id}" 依赖的步骤 "{dep_id}" 不存在')
        
        # 检查循环依赖
        if has_cyclic_dependency(steps):
            errors.append('工作流存在循环依赖')
        
        return {
            'valid': len(errors) == 0,
            'errors': errors
        }
        
    except Exception as e:
        return {
            'valid': False,
            'errors': [f'验证过程中出错: {str(e)}']
        }


def has_cyclic_dependency(steps):
    """检查是否存在循环依赖"""
    
    # 构建依赖图
    graph = {}
    for step in steps:
        step_id = step.get('id')
        depends_on = step.get('depends_on', [])
        graph[step_id] = depends_on
    
    # DFS检测循环
    visited = set()
    rec_stack = set()
    
    def dfs(node):
        if node in rec_stack:
            return True  # 发现循环
        if node in visited:
            return False
        
        visited.add(node)
        rec_stack.add(node)
        
        for neighbor in graph.get(node, []):
            if dfs(neighbor):
                return True
        
        rec_stack.remove(node)
        return False
    
    for step_id in graph:
        if dfs(step_id):
            return True
    
    return False


@login_required
def workflow_monitoring(request):
    """工作流监控页面"""
    
    # 获取筛选参数
    status_filter = request.GET.get('status', '')
    template_filter = request.GET.get('template', '')
    date_range = request.GET.get('date_range', '7')  # 默认7天
    
    # 计算时间范围
    end_date = timezone.now()
    start_date = end_date - timedelta(days=int(date_range))
    
    # 构建查询
    instances = WorkflowInstance.objects.select_related('template', 'created_by').filter(
        created_at__range=[start_date, end_date]
    )
    
    if status_filter:
        instances = instances.filter(status=status_filter)
    
    if template_filter:
        instances = instances.filter(template_id=template_filter)
    
    instances = instances.order_by('-created_at')
    
    # 分页
    paginator = Paginator(instances, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # 统计数据
    stats = calculate_workflow_statistics(start_date, end_date)
    
    # 获取模板列表用于筛选
    templates = WorkflowTemplate.objects.filter(is_active=True)
    
    context = {
        'page_obj': page_obj,
        'stats': stats,
        'templates': templates,
        'current_filters': {
            'status': status_filter,
            'template': template_filter,
            'date_range': date_range,
        },
        'status_choices': WorkflowInstance.INSTANCE_STATUS_CHOICES,
    }
    
    return render(request, 'assets/workflow/monitoring.html', context)


def calculate_workflow_statistics(start_date, end_date):
    """计算工作流统计数据"""
    
    instances = WorkflowInstance.objects.filter(
        created_at__range=[start_date, end_date]
    )
    
    # 基础统计
    total_count = instances.count()
    status_counts = {}
    
    for status_choice in WorkflowInstance.INSTANCE_STATUS_CHOICES:
        status_code = status_choice[0]
        count = instances.filter(status=status_code).count()
        status_counts[status_code] = count
    
    # 模板使用统计
    template_stats = instances.values('template__name').annotate(
        count=Count('id')
    ).order_by('-count')
    
    # 平均处理时间
    completed_instances = instances.filter(
        status='completed',
        started_at__isnull=False,
        completed_at__isnull=False
    )
    
    avg_processing_time = None
    if completed_instances.exists():
        total_time = sum([
            (instance.completed_at - instance.started_at).total_seconds()
            for instance in completed_instances
        ])
        avg_processing_time = total_time / completed_instances.count() / 3600  # 转换为小时
    
    # 任务统计
    tasks = WorkflowStepTask.objects.filter(
        workflow_instance__in=instances
    )
    
    task_stats = {
        'total_tasks': tasks.count(),
        'pending_tasks': tasks.filter(status='pending').count(),
        'completed_tasks': tasks.filter(status='completed').count(),
        'overdue_tasks': tasks.filter(
            status='pending',
            due_date__lt=timezone.now()
        ).count(),
    }
    
    return {
        'total_count': total_count,
        'status_counts': status_counts,
        'template_stats': list(template_stats),
        'avg_processing_time': avg_processing_time,
        'task_stats': task_stats,
    }


@login_required
def workflow_instance_detail(request, instance_id):
    """工作流实例详情"""
    
    instance = get_object_or_404(
        WorkflowInstance.objects.select_related('template', 'created_by'),
        id=instance_id
    )
    
    # 获取步骤任务
    tasks = instance.step_tasks.select_related('assignee').order_by('created_at')
    
    # 获取历史记录
    history = instance.history_records.select_related('operator', 'step_task').order_by('-created_at')
    
    # 计算进度
    total_steps = len(instance.template.get_steps())
    completed_steps = tasks.filter(status='completed').count()
    progress_percentage = (completed_steps / total_steps * 100) if total_steps > 0 else 0
    
    context = {
        'instance': instance,
        'tasks': tasks,
        'history': history,
        'progress_percentage': progress_percentage,
        'total_steps': total_steps,
        'completed_steps': completed_steps,
    }
    
    return render(request, 'assets/workflow/instance_detail.html', context)


@login_required
@require_http_methods(["POST"])
def start_workflow_instance(request, instance_id):
    """启动工作流实例"""
    
    try:
        instance = get_object_or_404(WorkflowInstance, id=instance_id)
        
        if instance.status != 'pending':
            return JsonResponse({
                'success': False,
                'message': f'工作流状态不正确: {instance.get_status_display()}'
            }, status=400)
        
        # 启动工作流
        success = workflow_engine.start_workflow(instance_id, request.user)
        
        if success:
            return JsonResponse({
                'success': True,
                'message': '工作流启动成功'
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '工作流启动失败'
            }, status=500)
        
    except Exception as e:
        logger.error(f"启动工作流实例失败: {e}")
        return JsonResponse({
            'success': False,
            'message': f'启动失败: {str(e)}'
        }, status=500)


@login_required
@require_http_methods(["POST"])
def cancel_workflow_instance(request, instance_id):
    """取消工作流实例"""
    
    try:
        instance = get_object_or_404(WorkflowInstance, id=instance_id)
        
        if instance.status not in ['pending', 'running']:
            return JsonResponse({
                'success': False,
                'message': f'工作流状态不正确: {instance.get_status_display()}'
            }, status=400)
        
        data = json.loads(request.body)
        reason = data.get('reason', '用户取消')
        
        # 取消工作流
        instance.cancel(reason)
        
        return JsonResponse({
            'success': True,
            'message': '工作流已取消'
        })
        
    except Exception as e:
        logger.error(f"取消工作流实例失败: {e}")
        return JsonResponse({
            'success': False,
            'message': f'取消失败: {str(e)}'
        }, status=500)


@login_required
def workflow_analytics(request):
    """工作流分析统计"""
    
    # 获取时间范围参数
    date_range = request.GET.get('date_range', '30')
    end_date = timezone.now()
    start_date = end_date - timedelta(days=int(date_range))
    
    # 基础统计
    stats = calculate_workflow_statistics(start_date, end_date)
    
    # 性能分析
    performance_data = calculate_workflow_performance(start_date, end_date)
    
    # 瓶颈分析
    bottleneck_data = analyze_workflow_bottlenecks(start_date, end_date)
    
    # 趋势分析
    trend_data = calculate_workflow_trends(start_date, end_date)
    
    context = {
        'stats': stats,
        'performance_data': json.dumps(performance_data),
        'bottleneck_data': bottleneck_data,
        'trend_data': json.dumps(trend_data),
        'date_range': date_range,
    }
    
    return render(request, 'assets/workflow/analytics.html', context)


def calculate_workflow_performance(start_date, end_date):
    """计算工作流性能数据"""
    
    # 按模板统计平均处理时间
    template_performance = []
    
    templates = WorkflowTemplate.objects.filter(is_active=True)
    
    for template in templates:
        instances = WorkflowInstance.objects.filter(
            template=template,
            status='completed',
            started_at__isnull=False,
            completed_at__isnull=False,
            created_at__range=[start_date, end_date]
        )
        
        if instances.exists():
            total_time = sum([
                (instance.completed_at - instance.started_at).total_seconds()
                for instance in instances
            ])
            avg_time = total_time / instances.count() / 3600  # 转换为小时
            
            template_performance.append({
                'template_name': template.name,
                'avg_processing_time': round(avg_time, 2),
                'instance_count': instances.count()
            })
    
    return {
        'template_performance': template_performance
    }


def analyze_workflow_bottlenecks(start_date, end_date):
    """分析工作流瓶颈"""
    
    bottlenecks = []
    
    # 分析超时任务
    overdue_tasks = WorkflowStepTask.objects.filter(
        created_at__range=[start_date, end_date],
        status='pending',
        due_date__lt=timezone.now()
    ).select_related('workflow_instance', 'assignee')
    
    if overdue_tasks.exists():
        bottlenecks.append({
            'type': 'overdue_tasks',
            'title': '超时任务',
            'count': overdue_tasks.count(),
            'description': f'有 {overdue_tasks.count()} 个任务已超时',
            'details': [
                {
                    'task_name': task.step_name,
                    'workflow_name': task.workflow_instance.instance_name,
                    'assignee': task.assignee.username if task.assignee else '未分配',
                    'overdue_hours': (timezone.now() - task.due_date).total_seconds() / 3600
                }
                for task in overdue_tasks[:5]  # 只显示前5个
            ]
        })
    
    # 分析处理时间过长的步骤类型
    slow_step_types = WorkflowStepTask.objects.filter(
        created_at__range=[start_date, end_date],
        status='completed',
        started_at__isnull=False,
        completed_at__isnull=False
    ).values('step_type').annotate(
        avg_time=Avg(F('completed_at') - F('started_at')),
        count=Count('id')
    ).order_by('-avg_time')
    
    for step_type_stat in slow_step_types[:3]:  # 前3个最慢的
        avg_hours = step_type_stat['avg_time'].total_seconds() / 3600
        if avg_hours > 24:  # 超过24小时的认为是瓶颈
            bottlenecks.append({
                'type': 'slow_step_type',
                'title': f'步骤类型处理缓慢',
                'count': step_type_stat['count'],
                'description': f'"{step_type_stat["step_type"]}" 类型步骤平均处理时间 {avg_hours:.1f} 小时',
            })
    
    return bottlenecks


def calculate_workflow_trends(start_date, end_date):
    """计算工作流趋势数据"""
    
    # 按天统计工作流创建数量
    daily_stats = []
    current_date = start_date.date()
    end_date_only = end_date.date()
    
    while current_date <= end_date_only:
        day_instances = WorkflowInstance.objects.filter(
            created_at__date=current_date
        )
        
        daily_stats.append({
            'date': current_date.strftime('%Y-%m-%d'),
            'created': day_instances.count(),
            'completed': day_instances.filter(status='completed').count(),
            'cancelled': day_instances.filter(status='cancelled').count(),
        })
        
        current_date += timedelta(days=1)
    
    return {
        'daily_stats': daily_stats
    }


@login_required
def workflow_template_clone(request, template_id):
    """克隆工作流模板"""
    
    try:
        original_template = get_object_or_404(WorkflowTemplate, id=template_id)
        
        # 创建克隆模板
        cloned_template = WorkflowTemplate.objects.create(
            name=f"{original_template.name} (副本)",
            template_type=original_template.template_type,
            description=f"克隆自: {original_template.name}",
            workflow_definition=original_template.workflow_definition,
            created_by=request.user
        )
        
        messages.success(request, f'工作流模板 "{original_template.name}" 克隆成功')
        return redirect('assets:workflow_template_edit', pk=cloned_template.id)
        
    except Exception as e:
        logger.error(f"克隆工作流模板失败: {e}")
        messages.error(request, f'克隆失败: {str(e)}')
        return redirect('assets:workflow_template_list')


@login_required
@require_http_methods(["GET"])
def workflow_template_export(request, template_id):
    """导出工作流模板"""
    
    try:
        template = get_object_or_404(WorkflowTemplate, id=template_id)
        
        export_data = {
            'name': template.name,
            'template_type': template.template_type,
            'description': template.description,
            'workflow_definition': template.workflow_definition,
            'version': template.version,
            'exported_at': timezone.now().isoformat(),
            'exported_by': request.user.username
        }
        
        response = JsonResponse(export_data, json_dumps_params={'indent': 2})
        response['Content-Disposition'] = f'attachment; filename="{template.name}_workflow_template.json"'
        
        return response
        
    except Exception as e:
        logger.error(f"导出工作流模板失败: {e}")
        return JsonResponse({
            'error': f'导出失败: {str(e)}'
        }, status=500)


@login_required
@permission_required('assets.add_workflowtemplate', raise_exception=True)
@require_http_methods(["POST"])
def workflow_template_import(request):
    """导入工作流模板"""
    
    try:
        uploaded_file = request.FILES.get('file')
        if not uploaded_file:
            return JsonResponse({
                'success': False,
                'message': '请选择要导入的文件'
            }, status=400)
        
        # 解析JSON文件
        content = uploaded_file.read().decode('utf-8')
        template_data = json.loads(content)
        
        # 验证数据
        required_fields = ['name', 'template_type', 'workflow_definition']
        for field in required_fields:
            if field not in template_data:
                return JsonResponse({
                    'success': False,
                    'message': f'缺少必要字段: {field}'
                }, status=400)
        
        # 验证工作流定义
        validation_result = validate_workflow_definition(template_data['workflow_definition'])
        if not validation_result['valid']:
            return JsonResponse({
                'success': False,
                'message': '工作流定义验证失败',
                'errors': validation_result['errors']
            }, status=400)
        
        # 创建模板
        template = WorkflowTemplate.objects.create(
            name=template_data['name'],
            template_type=template_data['template_type'],
            description=template_data.get('description', ''),
            workflow_definition=template_data['workflow_definition'],
            created_by=request.user
        )
        
        return JsonResponse({
            'success': True,
            'message': '工作流模板导入成功',
            'template_id': template.id
        })
        
    except json.JSONDecodeError:
        return JsonResponse({
            'success': False,
            'message': '文件格式错误，请上传有效的JSON文件'
        }, status=400)
    except Exception as e:
        logger.error(f"导入工作流模板失败: {e}")
        return JsonResponse({
            'success': False,
            'message': f'导入失败: {str(e)}'
        }, status=500)